﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace VidoopSecure
{
    static public class Util
    {
        /// <summary>
        /// Separator used between username and password in the service credentials.
        /// </summary>
        public const char CREDENTIALS_SEPARATOR = ':';

        /// <summary>
        /// Creates a string formatted as parameters for an HTTP POST operation.
        /// </summary>
        /// <param name="parameters">Key-value pair representing parameters.</param>
        /// <returns>Formatted string of parameters for an HTTP POST operation.</returns>
        static public string CreatePostParamsString(Dictionary<string, string> parameters)
        {
            string result = CreateQueryParamsString(parameters);
            return "&" + result;
        }

        /// <summary>
        /// Creates a string formatted as parameters for an HTTP GET operation.
        /// </summary>
        /// <param name="parameters">Key-value pair representing the parameters.</param>
        /// <returns>Formatted string of parameters for an HTTP GET operation.</returns>
        static public string CreateQueryParamsString(Dictionary<string, string> parameters)
        {
            if (parameters == null || parameters.Count == 0)
                return string.Empty;

            StringBuilder querySB = new StringBuilder();

            foreach (KeyValuePair<string, string> pair in parameters)
            {
                querySB.Append(string.Format("{0}={1}&", Uri.EscapeDataString(pair.Key), Uri.EscapeDataString(pair.Value)));
            }

            string queryStr = querySB.ToString();

            queryStr = queryStr.Substring(0, queryStr.Length - 1);

            return queryStr;
        }

        /// <summary>
        /// Parses the username and password out of <paramref name="credentials"/>
        /// using <see cref="VidoopSecure.Util.CREDENTIALS_SEPARATOR" /> as a separator.
        /// </summary>
        /// <param name="credentials">String containing username and password separated by
        /// <see cref="VidoopSecure.Util.CREDENTIALS_SEPARATOR" />.</param>
        /// <param name="username">Username parsed from <paramref name="credentials"/>.</param>
        /// <param name="password">Password parsed from <paramref name="credentials"/>.</param>
        static public void ParseCredentials(string credentials, out string username, out string password)
        {
            username = string.Empty;
            password = string.Empty;

            if (string.IsNullOrEmpty(credentials))
                return;

            string[] tokens = credentials.Split(new char[] {CREDENTIALS_SEPARATOR}, 2);
            if (tokens.Length == 2)
            {
                username = tokens[0];
                password = tokens[1];
            }
        }

        /// <summary>
        /// Base64 encode a string.
        /// </summary>
        /// <param name="toEncode">String to encode.</param>
        /// <returns>Encoded string.</returns>
        static public string EncodeTo64(string toEncode)
        {
            byte[] toEncodeAsBytes
                  = System.Text.UTF8Encoding.Unicode.GetBytes(toEncode);
            string returnValue
                  = System.Convert.ToBase64String(toEncodeAsBytes);
            return returnValue;
        }

        /// <summary>
        /// Returns the HTTP status code associated with a 
        /// <see cref="System.Net.WebException" />.
        /// </summary>
        /// <param name="exception">A <see cref="System.Net.WebException" />.</param>
        /// <returns>An integer representing an HTTP Status Code.</returns>
        static public int GetHttpStatus(WebException exception)
        {
            if (exception == null)
                throw new ApplicationException("GetHttpStatus expects a WebException argument.");

            int index = exception.Message.IndexOf(':');
            if (index > 0)
            {
                index = exception.Message.IndexOf('(', index);
                if (index > 0)
                {
                    int indexEnd = exception.Message.IndexOf(')', index);
                    if (indexEnd > index)
                    {
                        string code = exception.Message.Substring(index + 1, indexEnd - index - 1);

                        try
                        {
                            return int.Parse(code);
                        }
                        catch
                        {
                        }
                    }
                }
            }

            throw new ApplicationException(
                string.Format("GetHttpStatus unable to find status code in {0}",
                    exception.Message));
        }
    }
}
